﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using WindowsPhoneToolbox.Util;
using AppRes = WindowsPhoneToolbox.Resources;

namespace WindowsPhoneToolbox.Controls
{
    /// <summary>
    /// Interaction logic for ExplorerPhoneControl.xaml
    /// </summary>
    public partial class ExplorerPhoneControl
    {
        private IsoFilesView _isoFiles;

        public ExplorerPhoneControl()
        {
            InitializeComponent();
            StackSeleted.Visibility = Visibility.Collapsed;
            ReadSetting();
        }

        private void ShowDateUpdate()
        {
            DateUpdate.Text = AppRes.LastUpdate + DateTime.Now.ToShortDateString() + " " +
                              DateTime.Now.ToLongTimeString();
        }

        public static readonly RoutedEvent IsoExplorerEvent =
            EventManager.RegisterRoutedEvent("IsoExplorerCommand", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(ExplorerPhoneControl));

        public event RoutedEventHandler IsoExplorerCommand
        {
            add { AddHandler(IsoExplorerEvent, value); }
            remove { RemoveHandler(IsoExplorerEvent, value); }
        }

        private string _application;

        public string Application
        {
            get { return _application; }
            set
            {
                _application = value;
                TreeView.IsEnabled = false;
                LoadFiles();
                TreeView.IsEnabled = true;
            }
        }

        private void LoadFiles()
        {
            TreeView.Items.Clear();
            StackSeleted.Visibility = Visibility.Collapsed;
            DateUpdate.Text = AppRes.LastUpdate;
            if (WPhoneDevice.CurrentDevice == null || (WPhoneDevice.CurrentDevice != null && !WPhoneDevice.CurrentDevice.IsConnected()))
            {
                MessageBox.Show(AppRes.ConnectionLost,AppRes.TitleWindows, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            _isoFiles = null;
            if (string.IsNullOrEmpty(_application))
            {
                return;
            }
            _isoFiles = WPhoneDevice.GetIsoFiles(_application);
            ShowDateUpdate();
            //create treeview
            var app = WPhoneDevice.CurrentDevice.GetApplication(new Guid(_application));
            var tit = app.ProductID.ToString();
            try
            {
                if (!string.IsNullOrEmpty(app.Title))
                {
                    tit = app.Title;
                }
            }
            catch
            {
                var item = WpIsolateSaveData.Current.WpApplication.Find(a => a.Guid == app.ProductID.ToString());
                if (item != null)
                {
                    tit = item.Title;
                }
            }
            var root = new TreeViewWithIcons
            {
                HeaderText = tit,
                Icon =
                    new BitmapImage(
                    new Uri(Constants.RootResource + Constants.ApplicationIcon,
                            UriKind.RelativeOrAbsolute)),
                IconHeight = 16,
                IconWidth = 16,
                Tag = _isoFiles.Id
            };
            //root
            TreeView.Items.Add(root);
            if (_isoFiles.Files == null)
            {
                root.MouseRightButtonUp += DirectoryMouseRightButtonUp;
                root.PreviewMouseRightButtonDown += PreviewDirectoryMouseRightButtonDown;
                root.ExpandSubtree();
                return;
            }
            //create Strutuct
            foreach (var isoFilesView in _isoFiles.Files)
            {
                if (isoFilesView.IsDiretory)
                {
                    AddDirectory(root, isoFilesView);
                }
                else
                {
                    AddFile(root, isoFilesView);
                }
            }
            root.MouseRightButtonUp += DirectoryMouseRightButtonUp;
            root.PreviewMouseRightButtonDown += PreviewDirectoryMouseRightButtonDown;
            root.ChangeCheckItem += TreeChangeCheckItem;
            root.ExpandSubtree();
        }

        private void TreeChangeCheckItem(object sender, RoutedEventArgs e)
        {
            var tmp = ((TreeViewCheckClickEvent)e).TreeItem;
            SetIsChecked(tmp,true,true);
            var mark = ((TreeViewWithIcons) TreeView.Items[0]).Checked;
            if (!mark.HasValue)
            {
                StackSeleted.Visibility = Visibility.Visible;
            }
            else
            {
                StackSeleted.Visibility = mark.Value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        private  void SetIsChecked(TreeViewWithIcons item, bool updateChildren, bool updateParent)
        {
            if (updateChildren)
            {
                item.Checked = item.Checked.HasValue && item.Checked.Value;

                CheckedisoFile(_isoFiles, item.Tag.ToString(), item.Checked.Value);

                foreach (TreeViewWithIcons subitem in item.Items)
                {
                    subitem.Checked = item.Checked.Value;
                    CheckedisoFile(_isoFiles, subitem.Tag.ToString(), subitem.Checked.Value);
                    if (subitem.Items.Count > 0)
                    {
                        SetIsChecked(subitem,true,false);
                    }
                }
            }
            if (updateParent && item.Parent != null)
            {
                var treeViewWithIcons = item.Parent as TreeViewWithIcons;
                if (treeViewWithIcons != null)
                {
                    VerifyCheckState(treeViewWithIcons);
                }
            }
        }

        private  void VerifyCheckState(TreeViewWithIcons item)
        {
            bool? state = null;
            for (var i = 0; i < item.Items.Count; ++i)
            {
                var current = ((TreeViewWithIcons)item.Items[i]).Checked;
                if (i == 0)
                {
                    state = current;
                }
                else if (state != current)
                {
                    state = null;
                    break;
                }
            }
            item.Checked = state;
            if (!item.Checked.HasValue || (item.Checked.HasValue && item.Checked.Value))
            {
                CheckedisoFile(_isoFiles, item.Tag.ToString(), true);
            }
            else 
            {
                CheckedisoFile(_isoFiles, item.Tag.ToString(), false);
            }
            if (item.Parent != null)
            {
                var treeViewWithIcons = item.Parent as TreeViewWithIcons;
                if (treeViewWithIcons != null)
                {
                    VerifyCheckState(treeViewWithIcons);
                }
            }
        }

        private static void PreviewDirectoryMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var item = (TreeViewItem)sender;
            item.Focus();
            item.IsSelected = true;
        }

        private void AddDirectory(ItemsControl root, IsoFilesView item)
        {
            item.Icon = GetIcon(item);
            var node = new TreeViewWithIcons
            {
                HeaderText = item.Name,
                Icon =
                    new BitmapImage(
                    new Uri(Constants.RootResource + item.Icon,
                            UriKind.RelativeOrAbsolute)),
                IconHeight = 16,
                IconWidth = 16,
                Tag = item.Id
            };
            if (item.Files != null)
            {
                foreach (var child in item.Files)
                {
                    if (child.IsDiretory)
                    {
                        AddDirectory(node, child);
                    }
                    else
                    {
                        AddFile(node, child);
                    }
                }
            }
            root.Items.Add(node);
            node.MouseRightButtonUp += DirectoryMouseRightButtonUp;
            node.PreviewMouseRightButtonDown += PreviewDirectoryMouseRightButtonDown;
            node.ChangeCheckItem += TreeChangeCheckItem;
            node.Expanded += RootOnExpanded;
            node.Collapsed += RootOnCollapsed;
        }

        private static void RootOnCollapsed(object sender, RoutedEventArgs e)
        {
            var item = (TreeViewWithIcons)sender;
            if (item.Items.Count > 0)
            {
                item.Icon =
                new BitmapImage(
                    new Uri(Constants.RootResource + Constants.FolderClose,
                            UriKind.RelativeOrAbsolute));
            }
            e.Handled = true;
        }

        private static void RootOnExpanded(object sender, RoutedEventArgs e)
        {
            var item = (TreeViewWithIcons)sender;
            if (item.Items.Count > 0)
            {
                item.Icon =
                    new BitmapImage(
                        new Uri(Constants.RootResource + Constants.FolderOpen,
                                UriKind.RelativeOrAbsolute));
            }
            else
            {
                item.Icon =
                    new BitmapImage(
                        new Uri(Constants.RootResource + Constants.FolderClose,
                                UriKind.RelativeOrAbsolute));
            }
            e.Handled = true;
        }

        private void AddFile(ItemsControl root, IsoFilesView item)
        {
            item.Icon = GetIcon(item);
            var node = new TreeViewWithIcons
            {
                HeaderText = item.Name,
                Icon =
                    new BitmapImage(
                    new Uri(Constants.RootResource + item.Icon,
                            UriKind.RelativeOrAbsolute)),
                IconHeight = 16,
                IconWidth = 16,
                Tag = item.Id
            };
            var tooptip = AppRes.File1 + item.Name + "\n" +
                          AppRes.Size + Common.FormatBytes(item.Length) + "\n" +
                          AppRes.Created + item.DateCreated.ToShortDateString() + "  " + item.DateCreated.ToLongTimeString() + "\n" +
                          AppRes.Written + item.DateWrite.ToShortDateString() + "  " + item.DateWrite.ToLongTimeString() + "\n" +
                          AppRes.Accessed + item.DateAccess.ToShortDateString() + "  " + item.DateAccess.ToLongTimeString();
            node.ToolTip = tooptip;
            node.MouseRightButtonUp += FileMouseRightButtonUp;
            node.MouseRightButtonDown += PreviewFileMouseRightButtonDown;
            node.ChangeCheckItem += TreeChangeCheckItem;
            root.Items.Add(node);
        }

        private static void PreviewFileMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var item = (TreeViewItem)sender;
            item.Focus();
            item.IsSelected = true;
        }

        private static IsoFilesView CheckedisoFile(IsoFilesView isof, string id, bool value)
        {
            IsoFilesView result = null;
            if (isof.Id == id)
            {
                isof.Seleted = value;
                return isof;
            }
            if (isof.Files != null)
            {
                foreach (var item in isof.Files)
                {
                    if (item.Id == id)
                    {
                        item.Seleted = value;
                        break;
                    }
                    if (item.Files != null)
                    {
                        result = CheckedisoFile(item, id,value);
                        if (result != null)
                        {
                            break;
                        }
                    }
                }
            }
            return result;
        }

        private static IsoFilesView FindisoFile(IsoFilesView isof, string id)
        {
            IsoFilesView result = null;
            if (isof.Id == id)
            {
                return isof;
            }
            if (isof.Files != null)
            {
                foreach (var item in isof.Files)
                {
                    if (item.Id == id)
                    {
                        result = item;
                        break;
                    }
                    if (item.Files != null)
                    {
                        result = FindisoFile(item, id);
                        if (result != null)
                        {
                            break;
                        }
                    }
                }
            }
            return result;
        }

        private void ShowFileMenu(FrameworkElement item)
        {

            var contextMenu = new ContextMenu();

            var menuitem = new MenuItem {Header = AppRes.CopyFile,Tag = "Copy",Icon = ExplorerIso.Resources["ImgCopy"]};
            menuitem.Click += FileMenuClick;
            contextMenu.Items.Add(menuitem);

            var isSys = FindisoFile(_isoFiles, item.Tag.ToString()).IsSystem;

            if (!isSys)
            {
                menuitem = new MenuItem {Header = AppRes.DeleteFile, Tag = "Delete", Icon = ExplorerIso.Resources["ImgDelete"]};
                menuitem.Click += FileMenuClick;
                contextMenu.Items.Add(menuitem);

                menuitem = new MenuItem { Header = AppRes.RenameFile, Tag = "Rename", Icon = ExplorerIso.Resources["ImgRename"] };
                menuitem.Click += FileMenuClick;
                contextMenu.Items.Add(menuitem);
            }
            item.ContextMenu = contextMenu;
            contextMenu.IsOpen = true;
        }

        private void FileMenuClick(object sender, RoutedEventArgs e)
        {
            var isofile = FindisoFile(_isoFiles, ((FrameworkElement)TreeView.SelectedItem).Tag.ToString());
            var command = ((FrameworkElement) sender).Tag.ToString();
            var tempact = IsoExplorerEvent;
            if (tempact != null)
            {
                var arg = new ExplorerPhoneEvent(isofile,command,_application) { RoutedEvent = tempact };
                RaiseEvent(arg);
            }
        }

        private void DirMenuClick(object sender, RoutedEventArgs e)
        {
            var isofile = FindisoFile(_isoFiles, ((FrameworkElement)TreeView.SelectedItem).Tag.ToString());
            var command = ((FrameworkElement)sender).Tag.ToString();
            var tempact = IsoExplorerEvent;
            if (tempact != null)
            {
                var arg = new ExplorerPhoneEvent(isofile, command, _application) { RoutedEvent = tempact };
                RaiseEvent(arg);
            }
        }

        private static int CountFiles(IsoFilesView item, bool recursive)
        {
            var qtd = 0;
            if (item.Files == null)
            {
                return 0;
            }
            foreach (var file in item.Files)
            {
                if (file.IsDiretory || file.IsRoot )
                {
                    if (recursive)
                    {
                        qtd += CountFiles(file,true);
                    }
                }
                else
                {
                    if (!file.IsSystem)
                    {
                        qtd++;
                    }
                }
            }
            return qtd;
        }

        private void ShowDirMenu(FrameworkElement item)
        {
            var isofile = FindisoFile(_isoFiles, ((FrameworkElement)TreeView.SelectedItem).Tag.ToString());

            var contextMenu = new ContextMenu();
            MenuItem menuitem;
            if (isofile.IsRoot)
            {
                menuitem = new MenuItem { Header = AppRes.Launch1, Tag="Launch", Icon = ExplorerIso.Resources["ImgRun"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);

                menuitem = new MenuItem { Header = AppRes.Uninstall, Tag = "Remove", Icon = ExplorerIso.Resources["ImgDelete"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);

                contextMenu.Items.Add(new Separator());
            }

            var qtdfiles = CountFiles(isofile, true);
            if (qtdfiles > 0)
            {
                menuitem = new MenuItem { Header = AppRes.CopyFolderAndFiles, Tag = "Copy", Icon = ExplorerIso.Resources["ImgCopy"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);
            }

            if (!isofile.IsRoot && !isofile.IsSystem)
            {
                menuitem = new MenuItem { Header = AppRes.DeleteFolder, Tag = "Delete", Icon = ExplorerIso.Resources["ImgDelete"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);
            }

            menuitem = new MenuItem { Header = AppRes.CreateFolder, Tag = "CreateFolder", Icon = ExplorerIso.Resources["ImgNewDir"] };
            menuitem.Click += DirMenuClick;
            contextMenu.Items.Add(menuitem);

            contextMenu.Items.Add(new Separator());

            menuitem = new MenuItem { Header = AppRes.AddFiles, Tag = "AddFiles", Icon = ExplorerIso.Resources["ImgAdd"] };
            menuitem.Click += DirMenuClick;
            contextMenu.Items.Add(menuitem);

            var qtdfilesinfolder = CountFiles(isofile, false);
            if (isofile.IsRoot && qtdfilesinfolder > 0)
            {
                menuitem = new MenuItem { Header = AppRes.DeleteFilesRoot, Tag = "DeleteAll", Icon = ExplorerIso.Resources["ImgDeleteFiles"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);
            }
            else if (qtdfilesinfolder > 0)
            {
                menuitem = new MenuItem { Header = AppRes.DeleteFilesFolder, Tag = "DeleteAll", Icon = ExplorerIso.Resources["ImgDeleteFiles"] };
                menuitem.Click += DirMenuClick;
                contextMenu.Items.Add(menuitem);
            }

            item.ContextMenu = contextMenu;
            contextMenu.IsOpen = true;
        }

        private void FileMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var oldcur = Cursor;
            Cursor = System.Windows.Input.Cursors.Wait;
            var item = (TreeViewItem)sender;
            item.IsSelected = true;
            ShowFileMenu(item);
            e.Handled = true;
            Cursor = oldcur;
        }

        private void DirectoryMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var oldcur = Cursor;
            Cursor = System.Windows.Input.Cursors.Wait;
            var item = (TreeViewItem)sender;
            item.IsSelected = true;
            ShowDirMenu(item);
            e.Handled = true;
            Cursor = oldcur;
        }

        private static string GetIcon(IsoFilesView item)
        {
            if (item.IsDiretory)
            {
                return Constants.FolderClose;
            }
            var pos = item.Name.LastIndexOf(".", StringComparison.Ordinal);
            var ext = string.Empty;
            if (pos > 0)
            {
                ext = item.Name.Substring(pos + 1);
            }
            switch (ext.ToUpper())
            {
                case "SDF":
                    return Constants.ExtSdf;
                case "BMP":
                    return Constants.ExtBmp;
                case "DLL":
                    return Constants.ExtDll;
                case "DOC":
                case "DOCX":
                    return Constants.ExtDoc;
                case "EXE":
                    return Constants.ExtExe;
                case "GIF":
                    return Constants.ExtGif;
                case "HTML":
                case "HTM":
                    return Constants.ExtHtm;
                case "JPG":
                    return Constants.ExtJpg;
                case "PDF":
                    return Constants.ExtPdf;
                case "PNG":
                    return Constants.ExtPng;
                case "PPT":
                case "PPTX":
                    return Constants.ExtPpt;
                case "XLS":
                case "XLSX":
                    return Constants.ExtXls;
                case "XML":
                    return Constants.ExtXml;
            }
            return Constants.FileDefault;
        }

        private void ChkAppRunClick(object sender, RoutedEventArgs e)
        {
            SaveSetting();
        }

        private void SaveSetting()
        {
            var filename = Path.Combine(FolderData(), Constants.SettingsFileName);

            using (var stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
            {
                var formatter = new System.Xml.Serialization.XmlSerializer(typeof(bool));
                var value = ChkAppRun.IsChecked.HasValue && ChkAppRun.IsChecked.Value;
                formatter.Serialize(stream, value);
            }
        }

        private void ReadSetting()
        {
            var filename = Path.Combine(FolderData(), Constants.SettingsFileName);

            var result = false;
            if (File.Exists((filename)))
            {
                using (var stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite))
                {
                    var formatter = new System.Xml.Serialization.XmlSerializer(typeof (bool));
                    result = (bool)formatter.Deserialize(stream);
                }
            }
            ChkAppRun.IsChecked = result;
        }

        private static string FolderData()
        {
            var toolFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Constants.SettingsFolder);
            if (!Directory.Exists(toolFolder))
                Directory.CreateDirectory(toolFolder);
            return toolFolder;
        }

        private void BntRefreshClick(object sender, RoutedEventArgs e)
        {
            var tempact = IsoExplorerEvent;
            if (tempact != null)
            {
                var arg = new ExplorerPhoneEvent(new IsoFilesView{IsRoot = true}, "Refresh", _application) { RoutedEvent = tempact };
                RaiseEvent(arg);
            }
        }

        private void ActselectMouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            ((TextBlock)sender).FontWeight = FontWeights.Bold; 
        }

        private void ActselectMouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            ((TextBlock)sender).FontWeight = FontWeights.Normal;
        }

        private void ActCopyselMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var tempact = IsoExplorerEvent;
            if (tempact != null)
            {
                var arg = new ExplorerPhoneEvent(_isoFiles,  "CopyFilesSeleted", _application) { RoutedEvent = tempact };
                RaiseEvent(arg);
            }
        }

        private void ActDeleteselMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var tempact = IsoExplorerEvent;
            if (tempact != null)
            {
                var arg = new ExplorerPhoneEvent(_isoFiles, "DeleteFilesSeleted", _application) { RoutedEvent = tempact };
                RaiseEvent(arg);
            }            
        }

    }
}
